package com.dzqd.ecop.crm.sim;

import java.io.InputStream;
import java.util.Stack;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * @author Rex
 *
 */
public class HeaderAndBodyResponseMerger {

	private Document doc;
	
	private Stack<Element> stack;
	
	private XMLInputFactory xmlInputFactory;
	
	public HeaderAndBodyResponseMerger(String rootName) throws ParserConfigurationException {
		createDocument();
		
		Element rootElement = createRootElement(rootName);
		
		initStack(rootElement);
	}

	private void createDocument() throws ParserConfigurationException {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		doc = builder.newDocument();
	}
	
	private Element createRootElement(String rootName) {
		Element rootElement = doc.createElementNS("http://www.gmcc.net/ngcrm/", rootName);
		doc.appendChild(rootElement);
		return rootElement;
	}
	
	private void initStack(Element rootElement) {
		stack = new Stack<Element>();
		stack.push(rootElement);
	}
	
	
	
	/**
	 * 合并两份xml文档，并去除多余空白字符。
	 * @param headerXMLFileStream 头部xml报文输入流
	 * @param bodyXMLFileStream 报文体xml报文输入流
	 * @return xml DOM 对象。
	 * @throws XMLStreamException 当xmlInputFactory.createXMLStreamReader(InputStream)方法异常时抛出。
	 */
	public Document merge(InputStream headerXMLFileStream, InputStream bodyXMLFileStream) throws XMLStreamException {
		createXMLInputFactory();
		parseFrom(headerXMLFileStream);
		parseFrom(bodyXMLFileStream);
		
		return doc;
	}

	private void createXMLInputFactory() throws FactoryConfigurationError {
		xmlInputFactory = XMLInputFactory.newInstance();
	}

	private void parseFrom(InputStream headerXMLFileStream)
			throws XMLStreamException {
		XMLStreamReader parser = xmlInputFactory.createXMLStreamReader(headerXMLFileStream, "utf-8");
		while(parser.hasNext()) {
			int event = parser.next();
			if(event == XMLStreamConstants.START_ELEMENT) {
				Element parentElement = stack.peek();
				
				Element element = doc.createElement(parser.getLocalName());
				
				createAllAttributes(parser, element);
				
				parentElement.appendChild(element);
				
				stack.push(element);
			} else if(event == XMLStreamConstants.CHARACTERS) {
				String text = parser.getText().trim();
				Element parentElement = stack.peek();
				parentElement.appendChild(doc.createTextNode(text));
			} else if(event == XMLStreamConstants.END_ELEMENT) {
				stack.pop();
			}
		}
	}

	private void createAllAttributes(XMLStreamReader parser, Element element) {
		int count = parser.getAttributeCount();
		for(int i = 0; i < count; i++) {
			String localName = parser.getAttributeLocalName(i);
			String value = parser.getAttributeValue(i);
			element.setAttribute(localName, value);
		}
	}
}
